
package com.e885.util.string;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;

import com.e885.util.numeric.RandomUtil;

/**
 * 有關字串的 util <br>
 * Copyright: Copyright (c) 2002-2007<br>
 * Company: E885 有限公司
 * 
 * @author Eric Gau(gau168.gau@msa.hinet.net)
 * @version 1.0
 */
public class StringUtil
{
	/**
	 * 身份證驗證程式
	 * 
	 * @param str 要驗證的身份證字串
	 * @return 如果驗證正確, 傳回 true, 否則傳回 false
	 */
	public static boolean checkIdentity( String str )
	{
		if( str == null )
		{
			return false;
		}

		// check length
		if( str.length() != 10 )
		{
			return false;
		}

		String[] codes =
			{ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "X", "Y", "O", "I" };

		int[] numbers =
			{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 34 };

		int total = 0;
		str = str.toUpperCase();
		String strFirst = str.substring( 0, 1 );
		String strNumber = str.substring( 1, 10 );

		// check format of first character
		if( !isLetter( strFirst ) )
		{
			return false;
		}

		// check format of number
		if( !isDigital( strNumber ) )
		{
			return false;
		}

		// check rule
		int lengthOfCodes = codes.length;
		for( int i = 0; i < lengthOfCodes; i++ )
		{
			if( strFirst.equals( codes[ i ] ) )
			{
				str = String.valueOf( numbers[ i ] ) + strNumber;
				break;
			}
		}

		for( int i = 10; i >= 1; i-- )
		{
			if( i == 10 )
			{
				total += Integer.parseInt( str.substring( 10 - i, 10 - i + 1 ) );
			}
			else
			{
				total += ( Integer.parseInt( str.substring( 10 - i, 10 - i + 1 ) ) * i );
			}
		}

		int value = 10 - total % 10;
		if( value == 10 )
		{
			value = 0;
		}

		return ( value == Integer.parseInt( strNumber.substring( 8, 9 ) ) );
	}

	/**
	 * 將字串陣列以分隔符號來組合, 如: computer,desk,room
	 * 
	 * @param source 字串陣列
	 * @param delim 分隔符號
	 * @return
	 */
	public static String composeByArray( String[] source, String delim )
	{
		if( source == null || source.length == 0 )
			return "";

		if( delim == null )
			throw new IllegalArgumentException( "delim is null" );

		StringBuffer buffer = new StringBuffer();

		buffer.append( source[ 0 ] );

		for( int i = 1; i < source.length; i++ )
		{
			buffer.append( delim );
			buffer.append( source[ i ] );
		}

		return buffer.toString();
	}

	/**
	 * 將字串陣列以分隔符號來組合, 並用引號包住, 如(使用雙引號): "computer","desk","room"
	 * 
	 * @param source 字串陣列
	 * @param delim 分隔符號
	 * @param quote 引號
	 * @return
	 */
	public static String composeByArray( String[] source, String delim, String quote )
	{
		if( source == null || source.length == 0 )
			return "";

		if( delim == null )
			throw new IllegalArgumentException( "delim is null" );

		if( quote == null )
			throw new IllegalArgumentException( "quote is null" );

		StringBuffer buffer = new StringBuffer();

		buffer.append( quote );
		buffer.append( source[ 0 ] );
		buffer.append( quote );

		for( int i = 1; i < source.length; i++ )
		{
			buffer.append( delim );
			buffer.append( quote );
			buffer.append( source[ i ] );
			buffer.append( quote );
		}

		return buffer.toString();
	}

	/**
	 * 取得一個由 0-9 亂數決定的字串, 如:長度(length) 指定為 3, 那回傳為 "285"
	 * 
	 * @param length int 要組合字串的長度
	 * @return String 回傳已組合的字串
	 */
	public static String composeDynamicNumber( int length )
	{
		return composeDynamicNumber( length, 10 );
	}

	/**
	 * 取得一個由 <code>number</code> 亂數決定的字串, 如 length: 3, number:4(0-3), 那麼回傳值可能為 "123", "333", "201" 等等
	 * 
	 * @param length 要組合字串的長度
	 * @param number 亂數決定數值的範圍, 但不能超過
	 * @return 回傳已組合的字串
	 */
	public static String composeDynamicNumber( int length, int number )
	{
		if( number > 10 || number < 1 )
		{
			throw new IllegalArgumentException( "number is error" );
		}

		StringBuffer buffer = new StringBuffer();

		for( int i = 0; i < length; i++ )
		{
			buffer.append( String.valueOf( RandomUtil.getIntegerNumber( number ).intValue() ) );
		}

		return buffer.toString();
	}

	/**
	 * 取得大量身份證字號
	 * 
	 * @param quantity int 取得的數量
	 * @return String[] 大量身份證字號
	 */
	public static String[] fetchQuantyIdentities( int quantity )
	{
		String[] identities = new String[ quantity ];

		for( int i = 0; i < quantity; i++ )
		{
			identities[ i ] = fetchRandomIdentity();
		}

		return identities;
	}

	/**
	 * 以亂數的方式, 取得身份證字號
	 * 
	 * @return String 身份證字號
	 */
	public static String fetchRandomIdentity()
	{
		StringBuffer buffer = new StringBuffer();

		String[] codes =
			{ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "X", "Y", "O", "I" };

		int[] numbers =
			{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 34 };

		buffer.append( numbers[ RandomUtil.getIntegerNumber( numbers.length ).intValue() ] );
		buffer.append( RandomUtil.getIntegerNumber( 2 ).intValue() + 1 );
		buffer.append( composeDynamicNumber( 7 ) );

		int value = Integer.parseInt( buffer.substring( 0, 1 ) );
		for( int i = 1; i < 10; i++ )
		{
			value += Integer.parseInt( buffer.substring( i, i + 1 ) ) * ( 10 - i );
		}

		value = value % 10;

		if( value == 0 )
		{
			value = 10;
		}

		buffer.append( ( 10 - value ) );

		int index = fingerArrayIndex( numbers, Integer.parseInt( buffer.substring( 0, 2 ) ) );

		buffer.replace( 0, 2, codes[ index ] );

		return buffer.toString();
	}

	/**
	 * 以亂數取得性別, 男:M, 女:F
	 * 
	 * @return
	 */
	public static String fetchRandomSex()
	{
		if( RandomUtil.getIntegerNumber( 2 ).intValue() == 0 )
			return "M";
		else
			return "F";
	}

	/**
	 * 搜尋一個數字在數字陣列的位置
	 * 
	 * @param numbers 數字陣列
	 * @param number 要搜尋的數字
	 * @return 搜尋到, 傳回數字所在位置, 沒有搜尋到, 傳回 -1
	 */
	public static int fingerArrayIndex( int[] numbers, int number )
	{
		int length = numbers.length;

		for( int i = 0; i < length; i++ )
		{
			if( numbers[ i ] == number )
			{
				return i;
			}
		}

		return -1;
	}

	/**
	 * 搜尋一個字串在字串陣列的位置
	 * 
	 * @param strs String[] 字串陣列
	 * @param source String 要搜尋的字串
	 * @return int 搜尋到, 傳回字串所在位置, 沒有搜尋到, 傳回 -1
	 */
	public static int fingerArrayIndex( String[] strs, String source )
	{
		int length = strs.length;

		for( int i = 0; i < length; i++ )
		{
			if( strs[ i ].equals( source ) )
			{
				return i;
			}
		}

		return -1;
	}

	/**
	 * 由指定的字串, 指定的次數, 重覆產生指定的字串成為字串<br>
	 * 如: count = 2, str = "test"<br>
	 * return string is "testtest"
	 * 
	 * @param count 重覆次數
	 * @param str 要產生的重覆字串
	 * @return 依重覆次數產生出來的字串
	 */
	public static String generateString( int count, String str )
	{
		StringBuffer buffer = new StringBuffer();
		for( int i = 0; i < count; i++ )
		{
			buffer.append( str );
		}
		return buffer.toString();
	}

	/**
	 * 取得字串, 如果為 null 或空字串, 傳回 null
	 * 
	 * @param source
	 * @return
	 */
	public static String getString( String source )
	{
		if( source == null || source.length() == 0 )
			return null;

		return source;
	}

	/**
	 * 檢查字串的每個字元，是否為數字 0 到 9<br>
	 * 如: "520" return true<br>
	 * "5A0" return false
	 * 
	 * @param str 要檢查的字串
	 * @return false 表字串含有非數字 0 到 9 的字元
	 */
	public static boolean isDigital( String str )
	{
		if( str == null )
		{
			throw new IllegalArgumentException( "str is null" );
		}

		if( str.length() == 0 )
		{
			return false;
		}

		int lenghtoOfStr = str.length();

		for( int i = 0; i < lenghtoOfStr; i++ )
		{
			if( str.charAt( i ) < '0' || str.charAt( i ) > '9' )
			{
				return false;
			}
		}

		return true;
	}

	/**
	 * 檢查字串是否都為英文字母
	 * 
	 * @param str 要檢查的字串
	 * @return 如果是, 傳回 true, 否則傳 false
	 */
	public static boolean isLetter( String str )
	{
		if( str == null )
		{
			return false;
		}

		char ch;

		str = str.toUpperCase();

		int length = str.length();

		for( int i = 0; i < length; i++ )
		{
			ch = str.charAt( i );
			if( ch < 'A' || ch > 'Z' )
			{
				return false;
			}
		}

		return true;
	}

	/**
	 * 在字串前補上空白
	 * 
	 * @param source 要補空白的字串
	 * @param length 補完空白之後的字串長度
	 * @return 已補完空白的字串
	 */
	public static String pendingSpace( String source, int length )
	{
		return pendingString( source, length, " " );
	}

	/**
	 * 在字串前補上指定的字元
	 * 
	 * @param source 要補指定字元的字串
	 * @param length 補完指定字元的字串
	 * @param pendingValue 指定字元,長度要為 1
	 * @return 已補上字元的字串
	 */
	public static String pendingString( String source, int length, String pendingValue )
	{
		if( source == null )
			return null;

		if( pendingValue == null )
			throw new IllegalArgumentException( "pendingValue is null" );

		if( pendingValue.length() != 1 )
			throw new IllegalArgumentException( "the length of the pendingValue is null" );

		int sourceLength = source.length();

		if( length < sourceLength )
			return source;

		for( int i = 0; i < length - sourceLength; i++ )
		{
			source = pendingValue + source;
		}

		return source;
	}

	/**
	 * 在數字前補上 zero
	 * 
	 * @param value 要補 zero 的數字
	 * @param length 補完 zero 之後的字串長度
	 * @return 已補完 zero 的數字字串
	 */
	public static String pendingZero( int value, int length )
	{
		return pendingZero( String.valueOf( value ), length );
	}

	/**
	 * 在字串前補上 zero
	 * 
	 * @param str 要補 zero 的字串
	 * @param length 補完 zero 之後的字串長度
	 * @return 已補完 zero 的字串
	 */
	public static String pendingZero( String str, int length )
	{
		return pendingString( str, length, "0" );
	}

	/**
	 * 將字串倒過來,在這裏間隔符號使用 " "
	 * 
	 * @param source 字串來源, ex:"This is a test"
	 * @return reverse 後的字串, ex:"test a is This"
	 */
	public static String reverse( String source )
	{
		return reverse( source, " " );
	}

	/**
	 * 將字串倒過來,在這裏間隔符號使用指定的符號 <code>delim</code>
	 * 
	 * @param source 字串來源, ex:"This<delim>is<delim>a<delim>test"
	 * @param delim 指定的間隔符號
	 * @return reverse 後的字串, ex:"test<delim>a<delim>is<delim>This"
	 */
	public static String reverse( String source, String delim )
	{
		if( source == null || source.trim().length() == 0 )
		{
			return null;
		}

		if( delim == null || delim.length() == 0 )
		{
			throw new IllegalArgumentException( "The argument of the delim is error" );
		}

		Stack stack = new Stack();

		StringTokenizer tokenizer = new StringTokenizer( source, delim );

		while( tokenizer.hasMoreTokens() )
		{
			stack.push( tokenizer.nextToken() );
		}

		// 因為 stack 至少會有一個 element
		StringBuffer buffer = new StringBuffer( ( String )stack.pop() );

		while( !stack.empty() )
		{
			buffer.append( delim );
			buffer.append( ( String )stack.pop() );
		}

		return buffer.toString();
	}

	/**
	 * 將字串以 <code>delim</code>做拆解
	 * 
	 * @param source 字串來源
	 * @param delim 以這個字串做拆解
	 * @return 己拆解的字串陣列
	 */
	public static String[] split( String source, String delim )
	{
		List list = new ArrayList();

		StringTokenizer tokenizer = new StringTokenizer( source, delim );

		while( tokenizer.hasMoreTokens() )
		{
			list.add( tokenizer.nextToken() );
		}

		int size = list.size();

		String[] strs = new String[ size ];

		for( int i = 0; i < size; i++ )
		{
			strs[ i ] = ( String )list.get( i );
		}

		return strs;
	}
}
